﻿namespace LastfmNet.Api
{
    using System;
    using LastfmNet.Models;

    /// <summary>
    /// Last.fm API auth methods
    /// </summary>
    public class AuthApi
    {
        /// <summary>
        /// Reference to the Lastfm host class
        /// </summary>
        private Lastfm lastfmApi;

        /// <summary>
        /// Initializes a new instance of the AuthApi class.
        /// </summary>
        /// <param name="lastfmApi">Reference to the Lastfm host class</param>
        internal AuthApi(Lastfm lastfmApi)
        {
            this.lastfmApi = lastfmApi;
        }

        /// <summary>
        /// Create a web service session for a user. Used for authenticating a user when the password can be inputted by the user. Only suitable for standalone mobile devices. See the authentication how-to for more.
        /// This service does not require authentication.
        /// </summary>
        /// <param name="username">The last.fm username.</param>
        /// <param name="authToken">A 32-byte ASCII hexadecimal MD5 hash of the last.fm username and the user's password hash. i.e. md5(username + md5(password)), where '+' represents a concatenation.</param>
        /// <returns>Web service session for a user</returns>
        public Session GetMobileSession(string username, string authToken)
        {
            LastfmParameters parameters = new LastfmParameters("auth.getMobileSession");
            parameters["username"] = username;
            parameters["authToken"] = authToken;
            parameters.AddApiKey(this.lastfmApi.Session.ApiKey);
            parameters.Sign(this.lastfmApi.Session.ApiSecret);
            try
            {
                LastfmResponse result = this.lastfmApi.MakeRequest(parameters);
                return new Session(result.MainNode);
            }
            catch (Exception ex)
            {
                throw new LastfmNetException("Unable to get mobile session. Are your username and password correct?", ex);
            }
        }

        /// <summary>
        /// Fetch a session key for a user. The third step in the authentication process. See the authentication how-to for more information.
        /// This service does not require authentication.
        /// </summary>
        /// <param name="token">A 32-character ASCII hexadecimal MD5 hash returned by step 1 of the authentication process (following the granting of permissions to the application by the user)</param>
        /// <returns>Session key for a user</returns>
        public Session GetSession(string token)
        {
            LastfmParameters parameters = new LastfmParameters("auth.getSession");
            parameters["token"] = token;
            parameters.AddApiKey(this.lastfmApi.Session.ApiKey);
            parameters.Sign(this.lastfmApi.Session.ApiSecret);
            try
            {
                LastfmResponse result = this.lastfmApi.MakeRequest(parameters);
                return new Session(result.MainNode);
            }
            catch (Exception ex)
            {
                throw new LastfmNetException("Unable to get session. Is the token authorized?", ex);
            }
        }

        /// <summary>
        /// Fetch an unauthorized request token for an API account. This is step 2 of the authentication process for desktop applications. Web applications do not need to use this service.
        /// This service does not require authentication.
        /// </summary>
        /// <returns>Unathorized request token for an API account</returns>
        public string GetToken()
        {
            LastfmParameters parameters = new LastfmParameters("auth.getToken");
            parameters.AddApiKey(this.lastfmApi.Session.ApiKey);
            parameters.Sign(this.lastfmApi.Session.ApiSecret);
            try
            {
                LastfmResponse result = this.lastfmApi.MakeRequest(parameters);
                return result.MainNode.InnerText;
            }
            catch (Exception ex)
            {
                throw new LastfmNetException("Unable to get token. Are your API key and API secret correct?", ex);
            }
        }
    }
}
